package cn.anoxia.springframework.beans.factory;

import cn.anoxia.springframework.beans.BeansException;
import cn.anoxia.springframework.beans.PropertyValue;
import cn.anoxia.springframework.beans.PropertyValues;
import cn.anoxia.springframework.beans.factory.config.BeanFactoryPostProcessor;
import cn.anoxia.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import cn.anoxia.springframework.core.io.DefaultResourceLoader;
import cn.anoxia.springframework.core.io.Resource;
import cn.anoxia.springframework.utils.StringValueResolver;

import java.io.IOException;
import java.util.Properties;

/**
 * The class PropertyPlaceholderConfigurer.
 * <p>
 * Description:
 *
 * @author: huangle
 * @since: 2021/08/31 14:34
 */
public class PropertyPlaceholderConfigurer implements BeanFactoryPostProcessor {

  // 设置占位符
  public static final String DEFAULT_PLACEHOLDER_PREFIX = "${";

  public static final String DEFAULT_PLACEHOLDER_SUFFIX = "}";

  private String location;

  @Override
  public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    try {
      DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
      Resource resource = resourceLoader.getResource(this.location);
      Properties properties = new Properties();
      properties.load(resource.getInputStream());
      String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();

      for (String name : beanDefinitionNames) {
        BeanDefinition beanDefinition = beanFactory.getBeanDefinition(name);
        PropertyValues propertyValues = beanDefinition.getPropertyValues();
        for (PropertyValue propertyValue : propertyValues.getPropertyValues()) {
          Object value = propertyValue.getValue();
          if (!(value instanceof String)) {
            continue;
          }
          String strVal = (String) value;
          StringBuilder buffer = new StringBuilder();
          int startIdx = strVal.indexOf(DEFAULT_PLACEHOLDER_PREFIX);
          int endIdx = strVal.indexOf(DEFAULT_PLACEHOLDER_SUFFIX);
          if (startIdx != -1 && endIdx != -1 && startIdx < endIdx){
            String propKey = strVal.substring(startIdx + 2, endIdx);
            String property = properties.getProperty(propKey);
            buffer.replace(startIdx,endIdx+1,property);
            propertyValues.addPropertyValue(new PropertyValue(propertyValue.getName(),buffer.toString()));

          }
        }
      }

      PlaceholderResolvingStringValueResolver stringValueResolver = new PlaceholderResolvingStringValueResolver(properties);
      beanFactory.addEmbeddedValueResolver(stringValueResolver);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  private class PlaceholderResolvingStringValueResolver implements StringValueResolver{

    private final Properties properties;

    public PlaceholderResolvingStringValueResolver(Properties properties){
      this.properties = properties;
    }

    @Override
    public String resolveStringValue(String strVal) {
      return PropertyPlaceholderConfigurer.this.resolvePlaceholder(strVal, properties);
    }
  }

  public String getLocation() {
    return location;
  }

  public void setLocation(String location) {
    this.location = location;
  }

  /**
   * @Description: 解析${}内容
   * @author huangle
   * @Date 2021/9/1-17:04
   * @param value
   * @param properties
    * @return: java.lang.String
   */
  private String resolvePlaceholder(String value, Properties properties) {
    String strVal = value;
    StringBuilder buffer = new StringBuilder(strVal);
    int startIdx = strVal.indexOf(DEFAULT_PLACEHOLDER_PREFIX);
    int stopIdx = strVal.indexOf(DEFAULT_PLACEHOLDER_SUFFIX);
    if (startIdx != -1 && stopIdx != -1 && startIdx < stopIdx) {
      String propKey = strVal.substring(startIdx + 2, stopIdx);
      String propVal = properties.getProperty(propKey);
      buffer.replace(startIdx, stopIdx + 1, propVal);
    }
    return buffer.toString();
  }
}
